package mammuthus.controller.shell

import net.csdn.modules.http.{ViewType, RestRequest, ApplicationController}
import net.csdn.annotation.rest.{State, BasicInfo, At}
import com.google.inject.Inject
import mammuthus.master.Master
import mammuthus.slave.InteractiveShellCommand
import net.sf.json.{JSONArray, JSONObject}
import net.liftweb.{json => SJSon}
import mammuthus.docker.protocal.ListContainerRequest
import mammuthus.protocal.DockerRequest
import mammuthus.controller.filter.TokenAuthFilter

/**
 * 2/2/15 WilliamZhu(allwefantasy@gmail.com)
 */
class ShellTaskController @Inject()(akkaMaster: Master) extends ApplicationController with TokenAuthFilter{

  implicit val formats = SJSon.Serialization.formats(SJSon.NoTypeHints)


  @At(path = Array("/shell"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "指定哪些服务器执行对应的指令。返回 hostName -> taskId 的键值对",
    state = State.alpha,
    testParams = "?slaves=allwefantasy&shellCommand=date",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def shell = {
    auth
    val shellResps = akkaMaster.executeShellCommand(param("slaves", "pool-01"), param("shellCommand", "ls /"), paramAsLong("timeout",InteractiveShellCommand.defaultTimeOut))
    render(SJSon.Serialization.write(shellResps), ViewType.json)
  }

  @At(path = Array("/slaves"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "获取节点信息，包括hostName,ip(暂时为空),cpu(cores),memory(mb)等",
    state = State.alpha,
    testParams = "",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def slaves = {

    auth

    val result = akkaMaster.slaves.map(f=>f._2._2).toList

    if(paramAsBoolean("dockerDetail",false)){

      val hostNames = result.filter{f=>f.docker.enable}.map(f=>f.hostName).mkString(",")
      val dockerIdToInstanceDetails = akkaMaster.dockerContainerList(hostNames).flatMap(f=>f.instances).map(f=>(f.id,f)).toMap
      result.map{f=>
        if(dockerIdToInstanceDetails.contains(f.hostName)){
           akkaMaster.getCCParams(f) + ("dockerInstanceDetail" -> dockerIdToInstanceDetails(f.hostName))
        }else{
           akkaMaster.getCCParams(f)
        }
      }
    }
    render(SJSon.Serialization.write(result), ViewType.json)
  }

  @At(path = Array("/shell/process"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "通过指定的taskId获取shell执行的输出反馈",
    state = State.alpha,
    testParams = "?slaves=allwefantasy&taskId=---",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def shellProcess = {
    auth
    val shellResps = akkaMaster.shellCommandProcess(param("slaves", "pool-01"),
      param("taskId", ""),
      paramAsLong("offset", 0)
    )
    render(SJSon.Serialization.write(shellResps), ViewType.json)
  }

  @At(path = Array("/interactive/shell/start"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  def startShell = {
    auth
    val taskId = InteractiveShellCommand.start("scala", param("user", "system") + System.currentTimeMillis(), true)
    val result = new JSONArray
    val a = new JSONObject()
    a.put("taskId", taskId)
    result.add(a)
    render(result)
  }

  @At(path = Array("/interactive/shell"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  def interactiveShell = {
    auth
    InteractiveShellCommand.execute(param("taskId", "-"), param("line", "exit"))
    val result = new JSONArray
    val a = new JSONObject()
    a.put("taskId", param("taskId", "-"))
    result.add(a)
    render(result)
  }

  @At(path = Array("/interactive/shell/progress"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  def interactiveShellProgress = {
    auth
    val messageWithOffset = InteractiveShellCommand.progress(param("taskId", "-"), paramAsInt("offset", 0))
    render(SJSon.Serialization.write(messageWithOffset),ViewType.json)
  }
}
